// $Id: loghandler.cpp 65 2004-10-27 21:44:50Z hansemil $
#include "loghandler.h"
using namespace std;

/**
 * @todo Write documentation
 */
LogHandler::LogHandler()
:m_randomSeed(0)
{
	m_loggerEventLists["node_node"] = &m_node_node_list;
	m_loggerEventLists["node_requestFile"] = &m_node_requestFile_list;
	m_loggerEventLists["node_routeFile"] = &m_node_routeFile_list;
	m_loggerEventLists["node_transfer"] = &m_node_transfer_list;
	m_loggerEventLists["clock_tick"] = &m_clock_tick_list;
	m_loggerEventLists["network_transfer"] = &m_network_transfer_list;
}

/**
 * This will not run unless Singleton implements a manual clean()-method
 * @todo Implement this!
 */
LogHandler::~LogHandler()
{
	// Delete all Loggers
	/*for (map<const char *, list<Logger *> *>::iterator loggerList=m_loggerEventLists.begin(); loggerList!=m_loggerEventLists.end(); loggerList++) {
		for (list<Logger *>::iterator logger=(*loggerList).second->begin(); logger!=(*loggerList).second->end(); logger++) {
			delete *logger;
		}
		(*loggerList).second->clear();
	}*/
	for (list<Logger *>::iterator logger=m_loggers.begin(); logger!=m_loggers.end(); logger++) {
		delete *logger;
	}
}

/**
 * LogHandler owns and deletes all registered loggers.
 */
void LogHandler::addLogger(Logger *logger)
{
	m_loggers.push_back(logger);
}

/**
 * Add a logger object to a subscription list described by a string.
 * @todo Possible values on stringList
 *
 * @param logger The logger to add.
 * @param stringList A descriptive string to the list. (See ?what? for possible
 *  values)
 * @returns True if the logger was added. False otherwise.
 */
bool LogHandler::addLogger(Logger *logger, const char *stringList)
{
	list<Logger *> *list = m_loggerEventLists[stringList];
	if (list) {
		list->push_back(logger);
		return true;
	}
	return false;
}

/**
 * Called when the random seed has been decided.
 */
void LogHandler::main_seed(unsigned int seed)
{
	m_randomSeed = seed;
}

/**
 * Called just before the initialization of the simulation starts. This is sent to all Loggers.
 * @param eos Pointer to the eos object
 */
void LogHandler::eos_init_start(void *eos)
{
	for (list<Logger *>::iterator logger=m_loggers.begin(); logger!=m_loggers.end(); logger++) {
		(*logger)->eos_init_start(eos);
	}
}

/**
 * Called just before the simulation starts. This is sent to all Loggers.
 * @param eos Pointer to the eos object
 */
void LogHandler::eos_simulate_start(void *eos)
{
	for (list<Logger *>::iterator logger=m_loggers.begin(); logger!=m_loggers.end(); logger++) {
		(*logger)->eos_simulate_start(eos);
	}
}

/**
 * Called just after the simulation ends. This is sent to all Loggers.
 * @param eos Pointer to the eos object
 */
void LogHandler::eos_simulate_stop(void *eos)
{
	for (list<Logger *>::iterator logger=m_loggers.begin(); logger!=m_loggers.end(); logger++) {
		(*logger)->eos_simulate_stop(eos);
	}
}

/**
 * Called at the end of a Node construction.
 * @param eos Pointer to the new node object
 */
void LogHandler::node_node(void *node)
{
	for (list<Logger *>::iterator logger=m_node_node_list.begin(); logger!=m_node_node_list.end(); logger++) {
		(*logger)->node_node(node);
	}
}

/**
 * Called before each return from routeFile().
 *
 * @param thisNode (Node *) (Naming from caller nodes point of view) The node
 *  that called this method.
 * @param requestor (Node *) (Naming from caller nodes point of view) The node
 *  that initiated the request. If thisNode and requestor points to the same
 *  object, then that node was the initial requestor of the file.
 * @param params NodeRequestFileParameters containing the Node requestFile parameters
 * @param result The result returned by the request Zero for success and a
 * positive value for failure:
 * - 1 = Request ran out of Hop-To-Lives
 * - 2 = Seen this request before
 * - 3 = No more neighbors to ask
 * - 4 = Node is busy
 */
void LogHandler::node_routeFile(void *thisNode, void *requestor, void *params, unsigned char result)
{
	for (list<Logger *>::iterator logger=m_node_routeFile_list.begin(); logger!=m_node_routeFile_list.end(); logger++) {
		(*logger)->node_routeFile(thisNode, requestor, params, result);
	}
}

/**
 * Called before returning from requestFile() or insertFile()
 * @warning Note that this method is called on BOTH inserts AND requests, in spite of its name!
 *
 * @param thisNode (Node *) (Naming from caller nodes point of view) The node
 *  that called this method.
 * @param params NodeRequestFileParameters containing the Node requestFile parameters
 * @param result True if request was successful and false otherwise
 */
void LogHandler::node_requestFile(void *thisNode, void *params, bool result)
{
	for (list<Logger *>::iterator logger=m_node_requestFile_list.begin(); logger!=m_node_requestFile_list.end(); logger++) {
		(*logger)->node_requestFile(thisNode, params, result);
	}
}
/**
 * Called when a transfer is initiated and when it is stopped.
 *
 * @param sender (Node *) The node that sends the file.
 * @param transfer (Transfer *) A pointer to the transfer in question.
 * @param status Set to 0 if a request transfer is just started, 1 if a insert transfer just started and 2 if the
 *  transfer is finished.
 */
void LogHandler::node_transfer(void *sender, void *transfer, unsigned char status)
{
	for (list<Logger *>::iterator logger=m_node_transfer_list.begin(); logger!=m_node_transfer_list.end(); logger++) {
		(*logger)->node_transfer(sender, transfer, status);
	}
}

/**
 * Called each time Clock is ticked before the actual tick is done.
 *
 * @param time The current time (tick count)
 */
void LogHandler::clock_tick(unsigned int time)
{
	for (list<Logger *>::iterator logger=m_clock_tick_list.begin(); logger!=m_clock_tick_list.end(); logger++) {
		(*logger)->clock_tick(time);
	}
}

/**
 * Called each time after the network class has transfered some bytes from a node. This can happen many times per transfer depending on the network model.
 *
 * @param sender (Node *) The node that sends the file.
 * @param transfer (Transfer *) A pointer to the transfer in question.
 * @param bytesSent The number of bytes sent
 */
void LogHandler::network_transfer(void *sender, void *transfer, unsigned int bytesSent)
{
	for (list<Logger *>::iterator logger=m_network_transfer_list.begin(); logger!=m_network_transfer_list.end(); logger++) {
		(*logger)->network_transfer(sender, transfer, bytesSent);
	}
}
